package com.chenfan.common.extension.mybatisplus.interceptor;

import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
import com.chenfan.common.extension.mybatisplus.assembler.ParameterObjectAssembler;
import org.apache.ibatis.binding.MapperMethod;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;

import java.sql.SQLException;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * DB交互参数对象拦截器
 *
 * @author wulg
 * @date 2021-09-02
 **/
public class ParameterObjectInnerInterceptor implements InnerInterceptor {

    private final ParameterObjectAssembler parameterObjectAssembler;

    public ParameterObjectInnerInterceptor(ParameterObjectAssembler parameterObjectAssembler) {
        this.parameterObjectAssembler = parameterObjectAssembler;
    }

    @Override
    public void beforeUpdate(Executor executor, MappedStatement ms, Object parameter) throws SQLException {
        if(parameter == null) {
            return;
        }
        SqlCommandType sqlCommandType = ms.getSqlCommandType();
        switch (sqlCommandType) {
            case INSERT:
                //可加入@TableField(fill =...)注解条件判断
                if(parameter instanceof MapperMethod.ParamMap) {
                    MapperMethod.ParamMap<Object> paramMap = (MapperMethod.ParamMap)parameter;
                    for(Map.Entry<String,Object> entry : paramMap.entrySet()) {
                        Object paramObject = entry.getValue();
                        if(paramObject == null) {
                            continue;
                        }
                        //mp默认仅支持 list, collection, array 3个命名，不然无法自动填充
                        if(paramObject instanceof Collection) {
                            //批量插入
                            ((Collection<Object>)paramObject).forEach(o -> {
                                this.insertIfNecessary(o);
                            });
                        } else  {
                            this.insertIfNecessary(paramObject);
                        }
                        break;
                    }
                } else {
                    this.insertIfNecessary(parameter);
                }
                break;
            case UPDATE:
                if(parameter instanceof MapperMethod.ParamMap) {
                    MapperMethod.ParamMap<Object> paramMap = (MapperMethod.ParamMap)parameter;
                    List<Object> paramList = paramMap.entrySet().stream().map(Map.Entry::getValue).distinct().collect(Collectors.toList());
                    for(Object paramObject : paramList) {
                        if(paramObject == null) {
                            continue;
                        } else {
                            this.updateIfNecessary(paramObject);
                        }
                    }
                }
                break;
            case SELECT:
                //租户隔离判断
                break;
            case DELETE:
                //租户隔离判断
                break;
            default:
                break;
        }
    }

    /**
     *
     * @param paramObject
     */
    private void insertIfNecessary(Object paramObject) {
        if(!parameterObjectAssembler.supportDml(paramObject.getClass())) {
            throw new UnsupportedOperationException("Non-entity class not allowed insert!");
        }
        parameterObjectAssembler.insertFill(paramObject);
    }

    /**
     *
     * @param paramObject
     */
    private void updateIfNecessary(Object paramObject) {
        if(!parameterObjectAssembler.supportDml(paramObject.getClass())) {
            throw new UnsupportedOperationException("Non-entity class not allowed update!");
        }
        //可加入@TableField(fill =...)注解条件判断
        parameterObjectAssembler.updateFill(paramObject);
        parameterObjectAssembler.preventUpdateOfImportantField(paramObject);
    }
}
